package com.hethongviet.preventingmachine.helps;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.telephony.SmsManager;
import android.view.View;

import com.hethongviet.preventingmachine.Config;
import com.hethongviet.preventingmachine.Constants;
import com.hethongviet.preventingmachine.R;
import com.hethongviet.preventingmachine.Utils;

import com.hethongviet.preventingmachine.models.Camera;
import com.hethongviet.preventingmachine.models.Transaction;
import com.hethongviet.preventingmachine.models.Relay;
import com.hethongviet.preventingmachine.models.Sensor;
import com.hethongviet.preventingmachine.models.Number;

public final class SMSHelper
{
	public static final char CODE_START = '@';
	public static final char CODE_END = '#';
	public static final char CODE_REPLACE_NULL = '*';
	public static final char CODE_SEPARATE = ';';

	public static final String CODE_OK = "OK";
	public static final String CODE_ERROR = "ERROR";
	public static final char CODE_ERROR_UPDATE = '!';
	public static final char CODE_RELAY_ANY = 'b';
	public static final char CODE_RELAY_ON = '1';

	public static final String CODE_CHANGE_PASSWORD = CODE_START + "00";

	public static final String CODE_SETUP_PHONE_ALARM = CODE_START + "01";

	public static final String CODE_SETUP_PHONE_CONTROL = CODE_START + "02";

	public static final String CODE_RENAME_RELAY = CODE_START + "03";

	public static final String CODE_RENAME_SENSOR = CODE_START + "04";

	public static final String CODE_RENAME_DEVICE = CODE_START + "05";

	public static final String CODE_UPDATE_ALL = CODE_START + "06";
	public static final String CODE_RESPONSE_UPDATE_ALL_SENSOR = CODE_UPDATE_ALL
			+ "1";
	public static final String CODE_RESPONSE_UPDATE_ALL_RELAY = CODE_UPDATE_ALL
			+ "2";
	public static final String CODE_RESPONSE_UPDATE_ALL_PHONE_ALARM = CODE_UPDATE_ALL
			+ "3";
	public static final String CODE_RESPONSE_UPDATE_ALL_PHONE_CONTROL = CODE_UPDATE_ALL
			+ "4";

	public static final String CODE_UPDATE_SENSOR = CODE_START + "07";
	public static final String CODE_RESPONSE_UPDATE_SENSOR = CODE_UPDATE_ALL
			+ "1";
	public static final String CODE_UPDATE_RELAY = CODE_START + "08";
	public static final String CODE_RESPONSE_UPDATE_RELAY = CODE_UPDATE_ALL
			+ "1";
	public static final String CODE_UPDATE_PHONE_ALARM = CODE_START + "09";
	public static final String CODE_RESPONSE_UPDATE_PHONE_ALARM = CODE_UPDATE_ALL
			+ "1";
	public static final String CODE_UPDATE_PHONE_CONTROL = CODE_START + "10";
	public static final String CODE_RESPONSE_UPDATE_PHONE_CONTROL = CODE_UPDATE_ALL
			+ "1";

	public static final String CODE_CONTROL_DEVICE = CODE_START + "11";
	public static final String CODE_ALARM = CODE_START + "50";

	public static final String CODE_SYNCHRONIZE_NUMBERS_ALARM = CODE_START
			+ "12";
	public static final String CODE_SYNCHRONIZE_NUMBERS_CONTROL = CODE_START
			+ "13";
	public static final String CODE_SYNCHRONIZE_CAMERA = CODE_START + "14";

	public static final String CODE_LOCK_1 = CODE_START + "15-10";
	public static final String CODE_UNLOCK_1 = CODE_START + "15-11";

	public static final String CODE_LOCK_2 = CODE_START + "15-20";
	public static final String CODE_UNLOCK_2 = CODE_START + "15-21";

	/* For debug */
	public static final String DEBUG_SMS_ID_DEFAULT = "000";
	public static final String DEBUG_SMS_CONTROL_DEVICE = CODE_CONTROL_DEVICE
			+ "(bbbb0bbbbb)#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_UPDATE_SENSORS = CODE_RESPONSE_UPDATE_ALL_SENSOR
			+ "(sensor1)(sensor2)(sensor3)(sensor4)(sensor5)(sensor6)(sensor7)(sensor8)(sensor9)(sensor10)-OK#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_UPDATE_RELAYS = CODE_RESPONSE_UPDATE_ALL_RELAY
			+ "(relay1)(relay2)(relay3)(relay4)(relay5)(relay6)(relay7)(relay8)-(1010010110)-(VSYS)-(20)-OK#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_UPDATE_ALL_1 = CODE_RESPONSE_UPDATE_ALL_SENSOR
			+ "(sensor1)(sensor2)(sensor3)(sensor4)(sensor5)(sensor6)(sensor7)(sensor8)(sensor9)(sensor10)-OK#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_UPDATE_ALL_2 = CODE_RESPONSE_UPDATE_ALL_RELAY
			+ "(**********)(**********)(**********)(**********)(**********)(**********)(**********)(**********)-(01010111)-(vsys.com)-(33.8)-OK#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_UPDATE_ALL_3 = CODE_RESPONSE_UPDATE_ALL_PHONE_ALARM
			+ "(******)(******)(******)(******)(******)(******)(******)(******)(******)(******)-OK#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_UPDATE_ALL_4 = CODE_RESPONSE_UPDATE_ALL_PHONE_CONTROL
			+ "(phone1)(phone2)(phone3)(phone4)(phone5)(phone6)(phone7)(phone8)(phone9)(phone10)-OK#"
			+ DEBUG_SMS_ID_DEFAULT;

	public static final String DEBUG_SMS_CHANGE_PASSWORD = CODE_CHANGE_PASSWORD
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_SETUP_NUMBERS_ALARM = CODE_SETUP_PHONE_ALARM
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_SETUP_NUMBERS_CONTROL = CODE_SETUP_PHONE_CONTROL
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_RENAME_RELAYS = CODE_RENAME_RELAY
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_RENAME_SENSORS = CODE_RENAME_SENSOR
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_RENAME_DEVICE = CODE_RENAME_DEVICE
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_SYNCHRONIZE_NUMBERS_ALARM = CODE_SYNCHRONIZE_NUMBERS_ALARM
			+ Constants.DEVICE_NUMBER_DEFAULT
			+ ";sensor1;sensor2;sensor3;sensor4;sensor5;sensor6;sensor7;sensor8;sensor9;sensor10#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_SYNCHRONIZE_NUMBERS_CONTROL = CODE_SYNCHRONIZE_NUMBERS_CONTROL
			+ Constants.DEVICE_NUMBER_DEFAULT
			+ ";relay1;relay2;relay3;relay4;relay5;relay6;relay7;relay8#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_SYNCHRONIZE_NUMBERS_CONTROL_USER = CODE_SYNCHRONIZE_NUMBERS_CONTROL
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_SYNCHRONIZE_NUMBERS_ALARM_USER = CODE_SYNCHRONIZE_NUMBERS_ALARM
			+ "-" + CODE_OK + "#" + DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_ALARM = CODE_ALARM + "(01)" + "#";
	public static final String DEBUG_SMS_CODE_LOCK_1 = CODE_LOCK_1 + "#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_CODE_LOCK_2 = CODE_LOCK_2 + "#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_CODE_UNLOCK_1 = CODE_UNLOCK_1 + "#"
			+ DEBUG_SMS_ID_DEFAULT;
	public static final String DEBUG_SMS_CODE_UNLOCK_2 = CODE_UNLOCK_2 + "#"
			+ DEBUG_SMS_ID_DEFAULT;

	private static String phoneNumberDevice = null;
	private static String password = null;

	/**
	 * the activity is activity and OnListenerSMSMessageFail
	 * */
	private static Activity activity = null;

	private static int countMessageId = 0;

	private static String getMessageId()
	{
		String id = "";
		if (countMessageId < 10)
		{
			id = "00" + countMessageId++;
		}
		else if (countMessageId < 100)
		{
			id = "0" + countMessageId++;
		}
		else
		{
			id = "" + countMessageId;
			if (countMessageId == 999)
			{
				countMessageId = 0;
			}
			else
				countMessageId++;

		}

		return id;
	}

	private static List<Transaction> transactionList = new ArrayList<Transaction>();

	public static Transaction solve(String messageReceive)
	{
		Utils.debug("Get the Transaction....from " + transactionList.size());
		String id = getIdCode(messageReceive);

		if (id == null || id.equals(""))
		{
			Utils.debug("ERROR----- null ID!");
			return null;
		}

		for (int i = 0; i < transactionList.size(); i++)
		{

			Transaction transaction = transactionList.get(i);
			Utils.debug("--search transaction.getId() = " + transaction.getId());

			if (transaction.getId().equals(id))
			{
				transactionList.remove(i);

				Utils.debug("last size = " + transactionList.size());

				if (transaction.isFail())
				{
					Utils.debug("Fail this transaction!");
					return null;
				}

				Utils.debug("*** Transaction matched! = " + id);

				transaction.setMessageReceive(getContent(messageReceive, transaction.getCodeSend().length()));

				transaction.success();

				return transaction;
			}
		}
		Utils.debug("Receive nothing!");
		return null;
	}

	public static String getDeviceNumber()
	{
		return phoneNumberDevice;
	}

	public static void setPassword(String pass)
	{
		password = pass;
	}

	public static void setMessageId(int id)
	{
		countMessageId = id;
	}

	public static String getContent(String message, int codeLength)
	{
		String content = "";
		for (int index = codeLength; index < message.length(); index++)
		{
			char c = message.charAt(index);
			if (c != CODE_END)
				content += c;
			else
			{
				Utils.debug("message content: " + content);
				return content;
			}
		}
		Utils.debug("message content: " + content);
		return content;
	}

	private static String getIdCode(String message)
	{
		String idCode = "";
		for (int index = message.length() - 1; index >= 0; index--)
		{
			char c = message.charAt(index);
			if (c != CODE_END)
				idCode = c + idCode;
			else
			{
				Utils.debug("message id: " + idCode);
				return idCode;
			}
		}
		Utils.debug("message id: " + idCode);
		return idCode;
	}

	public static void setDeviceNumber(String number)
	{
		phoneNumberDevice = number;
	}

	public static void setActivity(Activity activity1)
	{
		activity = activity1;
	}

	// ---sends an SMS message to another device---
	private static void sendSMSTo(String number, String code, String totals,
			int messageFailId, View view)
	{
		sendSMS(number, code, phoneNumberDevice + CODE_SEPARATE + totals
				+ CODE_END, messageFailId, null, view, false);
	}

	private static void sendSMSUserTo(String number, String code,
			String messageFailId, View view, boolean isUserSend)
	{
		sendSMS(number, code, "-" + CODE_OK + CODE_END, 0, messageFailId, view, isUserSend);
	}

	// ---sends an SMS message to another device---
	private static void sendSMS(String code, String message, int messageFailId,
			View view)
	{
		sendSMS(phoneNumberDevice, code, message, messageFailId, null, view, false);
	}

	// ---sends an SMS message to another device---
	private static void sendSMS(String number, String code, String message,
			int messageFailId, String idSent, View viewRelay, boolean isUserSend)
	{
		final String CODE_SENT = "SMS_SENT";
		final String CODE_DELIVERED = "SMS_DELIVERED";

		PendingIntent sentPendingIntent = PendingIntent.getBroadcast(activity, 0, new Intent(
				CODE_SENT), 0);

		PendingIntent deliveredPendingIntent = PendingIntent.getBroadcast(activity, 0, new Intent(
				CODE_DELIVERED), 0);

		// ---when the SMS has been sent---
		activity.registerReceiver(new BroadcastReceiver() {
			@Override
			public void onReceive(Context arg0, Intent arg1)
			{
				switch (getResultCode())
				{
					case Activity.RESULT_OK:
						Utils.toast(activity, R.string.message_SMS_send);
						break;
					case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
						Utils.toast(activity, R.string.message_error_SMS_send);
						break;
					case SmsManager.RESULT_ERROR_NO_SERVICE:
						Utils.toast(activity, R.string.message_error_SMS_not_available);
						break;
					case SmsManager.RESULT_ERROR_NULL_PDU:
						Utils.toast(activity, R.string.message_error_SMS_send);
						break;
					case SmsManager.RESULT_ERROR_RADIO_OFF:
						Utils.toast(activity, R.string.message_error_SMS_radio_off);
						break;
				}
			}
		}, new IntentFilter(CODE_SENT));

		// ---when the SMS has been delivered---
		activity.registerReceiver(new BroadcastReceiver() {
			@Override
			public void onReceive(Context arg0, Intent arg1)
			{
				switch (getResultCode())
				{
					case Activity.RESULT_OK:
						Utils.toast(activity, R.string.message_SMS_deliveried);
						break;
					case Activity.RESULT_CANCELED:
						Utils.toast(activity, R.string.message_error_SMS_not_deliveried);
						break;
				}
			}
		}, new IntentFilter(CODE_DELIVERED));

		Transaction transaction = new Transaction(
				(OnSMSMessageFailListener) activity, Constants.TIME_OUT_SMS,
				messageFailId, viewRelay);
		transaction.setId(getMessageId());
		transaction.setMessageSend(message);
		transaction.setCodeSend(code);
		transaction.setRecipient(number);

		if (!code.equals(CODE_UPDATE_ALL)// && number.equals(phoneNumberDevice)
				&& !isUserSend)
		{
			transactionList.add(transaction);
		}
		else
		{
			Utils.debug("SMS_HELPER: Code update all!!!!!");
		}

		if (!Config.IS_DEBUG_SMS_RECEIVE)
		{
			SmsManager sms = SmsManager.getDefault();
			String messageWillSend = Utils.isStringNull(idSent) ? transaction.getMessageWillSend()
					: transaction.getMessageWillSendNoID() + idSent;
			sms.sendTextMessage(number, null, messageWillSend, sentPendingIntent, deliveredPendingIntent);

			Utils.debug("---------Sending message via SMS = " + messageWillSend);
			Utils.debug("---------Sending message via SMS to " + number);
		}

	}

	public static boolean changePassword(String newPassword, int messageFail)
	{
		String message = "(" + password + ")(" + newPassword + ")" + CODE_END;

		sendSMS(CODE_CHANGE_PASSWORD, message, messageFail, null);
		return true;
	}

	public static boolean changeDeviceName(String name, int messageFail)
	{
		String message = "(" + password + ")(" + name + ")" + CODE_END;

		sendSMS(CODE_RENAME_DEVICE, message, messageFail, null);
		return true;
	}

	public static boolean updateAll()
	{
		String message = "(" + password + ")" + CODE_END + "";

		sendSMS(CODE_UPDATE_ALL, message, 0, null);
		return true;
	}

	public static boolean updateElement(String code, int messageFail)
	{
		String message = CODE_END + "";

		sendSMS(code, message, messageFail, null);
		return true;
	}

	public static boolean proccesslock(String code, int messageFail)
	{
		String message = CODE_END + "";

		sendSMS(code, message, messageFail, null);
		return true;
	}

	public static boolean setupAdmin(List<Number> numbers, String code,
			int messageFail)
	{
		String message = "(" + password + ")";
		for (Number number : numbers)
		{
			message += "(" + number.getNumber() + ")";
		}
		message += CODE_END;

		sendSMS(code, message, messageFail, null);
		return true;
	}

	public static boolean controlRelay(int totalRelays, int relayIndex,
			boolean isOn, int messageFail, View viewRelay)
	{
		String message = "(";

		for (int i = 0; i < totalRelays; i++)
		{
			if (i == relayIndex)
			{
				if (isOn)
					message += '1';
				else
					message += '0';
			}
			else
				message += 'b';
		}

		message += ")" + CODE_END;

		sendSMS(CODE_CONTROL_DEVICE, message, messageFail, viewRelay);
		return true;
	}

	public static boolean renameRelays(List<Relay> relays, int messageFail)
	{
		String message = "(" + password + ")";

		for (Relay relay : relays)
		{
			message += "(" + relay.getName() + ")";
		}
		message += CODE_END;

		sendSMS(CODE_RENAME_RELAY, message, messageFail, null);
		return true;
	}

	public static boolean renameSensors(List<Sensor> sensors, int messageFail)
	{
		String message = "(" + password + ")";

		for (Sensor sensor : sensors)
		{
			message += "(" + sensor.getName() + ")";
		}
		message += CODE_END;

		sendSMS(CODE_RENAME_SENSOR, message, messageFail, null);
		return true;
	}

	@SuppressWarnings("unchecked")
	public static boolean synchronize(String code, String number, String machineName,
			Object object, int messageFailId, List<Camera> cameras)
	{
		Utils.debug("Send message sychronize to numbers!!!!!!");
		if (number == null || number.length() == 0)
		{
			Utils.debug("Number null!!!!!!");
			return false;
		}

		String listNames = machineName + CODE_SEPARATE;
		if (object != null)
		{
			if (code.equals(CODE_SYNCHRONIZE_NUMBERS_ALARM))
			{
				List<Sensor> sensors = (List<Sensor>) object;
				for (Sensor sensor : sensors)
				{
					listNames += sensor.getName() + CODE_SEPARATE;
				}
			}
			else
			{
				List<Relay> relays = (List<Relay>) object;
				for (Relay relay : relays)
				{
					listNames += relay.getName() + CODE_SEPARATE;
				}
			}
		}

		sendSMSTo(number, code, listNames, messageFailId, null);

		return true;
	}

	public static boolean synchronizeOfUser(String number, String code,
			String idSent)
	{
		Utils.debug("Send message sychronize to admin!!!!!!");
		if (number == null || number.equals(""))
		{
			Utils.debug("Number null!!!!!!");
			return false;
		}

		sendSMSUserTo(number, code, idSent, null, true);

		return true;
	}

	public static boolean sendCamera(String number, List<Camera> cameras)
	{
		Utils.debug("Send message camera to number!!!!!!");
		if (number == null || number.equals(""))
		{
			Utils.debug("Number null!!!!!!");
			return false;
		}

		for (Camera camera : cameras)
		{
			sendSMS(CODE_SYNCHRONIZE_CAMERA, camera.getName() + CODE_SEPARATE
					+ camera.getAddress(), 0, null);
		}

		return true;
	}

}
